package com.sbtr.business.utils;

import org.junit.Test;

import java.io.*;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author maojianping
 */
public class ParamExtractorUtils {

    private static final String prefix = "ceprei_param_";
    private static final String regularJava = ".*(ceprei_param_[A-Za-z_]+)\\s*=\\s*(.*?)(?:\\/\\/.*)?";
    private static final String regularPython = "^\\s*(ceprei_param_[A-Za-z_]+)\\s*=\\s*(.*?)(?:#.*)?$";
    private static final String regularCpp = ".*(ceprei_param_[A-Za-z_]+)\\s*=\\s*(.*?)(?:\\/\\/.*)?";

    /**
     * 从给定的文件中提取Java变量并将其存储到HashMap中。
     * 变量的名称以 "ceprei_param_" 开头，后面跟随字母数字字符，变量名值可以是任意类型的表达式。
     * 支持public、private、protected、static和final关键字的任意组合，以及任意格式的变量定义语句
     * @param fileName 文件名
     * @throws IOException 如果读取文件时发生错误
     */
    public static HashMap<String, String> extractConstants(String fileName) throws IOException {

        HashMap<String, String> contentMap = new HashMap<>();
        BufferedReader br = new BufferedReader(new FileReader(fileName));
        String line;

        Pattern pattern = getPattern(fileName);

        while ((line = br.readLine()) != null) {
            if (line.contains("=") && line.contains(prefix)) {
                String[] paramArr = getConstant(line, pattern);
                if(null != paramArr)
                    contentMap.put(paramArr[0], paramArr[1]);
            }
        }
        br.close();

        return contentMap;
    }

    private static String[] getConstant(String line, Pattern pattern) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.matches()) {
            String name = matcher.group(1);
            String value = matcher.group(2);
            return new String[]{name, value};
        }
        return null;
    }

    public static String getFileExtension(String fileName) {
        String extension = "";
        int i = fileName.lastIndexOf('.');
        if (i > 0) {
            extension = fileName.substring(i + 1);
        }
        return extension;
    }

    public static Pattern getPattern(String fileName) {
        String fileExtension = getFileExtension(fileName);
        Pattern pattern = null;
        if (fileExtension.equals("java")) {
            pattern = Pattern.compile(regularJava);
        } else if (fileExtension.equals("py")) {
            pattern = Pattern.compile(regularPython);
        } else if (fileExtension.equals("cpp")) {
            pattern = Pattern.compile(regularCpp);
        }
        return pattern;
    }

    /**
     * 测试读取不同类型文件变量测试
     */
    @Test
    public void testReadConstants() throws IOException {
        System.err.println("----------testWriteConstants执行测试开始----------");

        String fileName1 = "e:/Anova_Formwork.java";
        HashMap<String, String> constants1 = extractConstants(fileName1);
        System.out.println("java类型算法模板："+constants1);

        String fileName2 = "e:/PCA_Formwork.py";
        HashMap<String, String> constants2 = extractConstants(fileName2);
        System.out.println("python类型算法模板："+constants2);

        String fileName3 = "e:/varianceal_culation_formwork.cpp";
        HashMap<String, String> constants3 = extractConstants(fileName3);
        System.out.println("C++类型算法模板："+constants3);
    }



    public static void writeConstants(String fileName, HashMap<String, String> paramMap) throws IOException {

        File file = new File(fileName);
        File temp = File.createTempFile("temp", null, file.getParentFile());
        BufferedReader br = new BufferedReader(new FileReader(file));
        PrintWriter pw = new PrintWriter(new FileWriter(temp));
        String line;

        Pattern pattern = getPattern(fileName);

        while ((line = br.readLine()) != null) {
            if (line.contains("=") && line.contains(prefix)) {
                String[] paramArr = getConstant(line, pattern);
                if (null!=paramArr && paramMap.containsKey(paramArr[0])){
                    line = replaceValue(line, pattern, paramArr, paramMap);
                }
            }
            pw.println(line);
        }
        br.close();
        pw.close();
        if (!file.delete())
            throw new IOException("删除原始文件失败: " + fileName);

        if (!temp.renameTo(file))
            throw new IOException("重命名临时文件失败!");
    }


    private static String replaceValue(String line, Pattern pattern,
                                       String[] paramArr, HashMap<String, String> paramMap) {
        String key = paramArr[0];
        String oldValue = paramArr[1];
        String newValue = paramMap.get(key);

        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            int start = matcher.start(2);
//            int end = matcher.end(2);
            int end = start+oldValue.length();
            StringBuilder builder = new StringBuilder(line.substring(0, start));
            builder.append(newValue);
            builder.append(line.substring(end));
            return builder.toString();
        }
        return line;
    }


    @Test
    public void testWriteConstants() throws IOException {
        System.err.println("----------testWriteConstants执行测试开始----------");
        File file = new File("e:/PCA.py");
        HashMap<String, String> constants = new HashMap<>();
        constants.put("ceprei_param_my_str", "\"ABCD\"");
        constants.put("ceprei_param_axis", "21");
        writeConstants(file.getAbsolutePath(), constants);

        File file1 = new File("e:/Anova_Formwork.java");
        HashMap<String, String> constants1 = new HashMap<>();
        constants1.put("ceprei_param_str", "\"PCA\"");
        constants1.put("ceprei_param_sst", "4");
        writeConstants(file1.getAbsolutePath(), constants1);

        File file2 = new File("e:/varianceal_culation.cpp");
        HashMap<String, String> constants2 = new HashMap<>();
        constants2.put("ceprei_param_variance", "1");
        constants2.put("ceprei_param_w", "\"test day\"");
        writeConstants(file2.getAbsolutePath(), constants2);
        System.err.println("----------testWriteConstants执行测试结束----------");
    }


}
